﻿using System;
using System.IO;
using System.Reflection;
using Abp.Dependency;
using Abp.Runtime.Caching;
using Microsoft.Extensions.FileProviders;

namespace KelonProud.Mvc.ViewEngine
{
    public class KelonProudVirtualPathFileInfo:IFileInfo
    {
        private bool _exists;
        private Stream _stream;
        private readonly string _resourcePath;

        public KelonProudVirtualPathFileInfo(string resourcePath)
        {
            _resourcePath = resourcePath;
            GetViewStream(_resourcePath);
        }

        public Stream CreateReadStream()
        {
            _stream = GetViewStream(_resourcePath);
            return _stream;
        }

        public bool Exists => _exists;
        public long Length => _stream.Length;
        public string PhysicalPath => null;
        public string Name => Path.GetFileName(_resourcePath);
        public DateTimeOffset LastModified => DateTimeOffset.Now;
        public bool IsDirectory => false;

        private Stream GetViewStream(string fullViewName)
        {
            fullViewName = fullViewName.Substring(fullViewName.ToLower().LastIndexOf("/", StringComparison.Ordinal)+1);

            var index = fullViewName.ToLower().IndexOf(".views", System.StringComparison.Ordinal);

            if (index == -1)
                return null;

            var assemblyName = fullViewName.Substring(0, index).ToLower();
            var assembly = GetAssembly(assemblyName);
            var stream = assembly.GetManifestResourceStream(fullViewName);

            _exists = stream != null;

            return stream;
        }

        private Assembly GetAssembly(string assemblyName)
        {
            var cashManager = IocManager.Instance.Resolve<ICacheManager>();
            var cash = cashManager.GetCache("viewCash");
            var assembly = cash.GetOrDefault(assemblyName) as Assembly;

            if (assembly != null) return assembly;

            assembly = Assembly.Load(assemblyName);
            cash.Set(assemblyName, assembly);

            return assembly;
        }
    }
}
